﻿Imports System.IO
Imports System.IO.IsolatedStorage
Imports System.Reflection
Imports System.Text.RegularExpressions
Imports System.Collections
Imports System.Collections.Specialized

''' <summary>
''' Manage QuickTuner files and folder organization.
''' </summary>
''' <remarks></remarks>
Public Module FileStore

    Private Const CACHEPREFIX As String = "cache-"
    Private Const CACHESUFFIX As String = ".qt!"

    Private _fileStore As IsolatedStorageFile

    Sub New()
        'loads the file store
        _fileStore = IsolatedStorageFile.GetUserStoreForApplication()
    End Sub

    ''' <summary>
    ''' Checks if the file store has the specified filename.
    ''' </summary>
    ''' <param name="filename">The filename to search for. Wildcards ? and * are allowed.</param>
    ''' <returns>True if the filestore contains the specified file, False otherwise.</returns>
    ''' <remarks></remarks>
    Public Function ContainsFile(ByVal filename As String) As Boolean
        Return _fileStore.GetFileNames(filename).Length > 0
    End Function

    ''' <summary>
    ''' Checks if there is a cached copy of the specified url available in the file store.
    ''' </summary>
    ''' <param name="url">The url to look for.</param>
    ''' <returns>True if there is a cached copy of the specified url, False otherwise.</returns>
    ''' <remarks></remarks>
    Public Function ContainsUrlCache(ByVal url As String) As Boolean
        Return _fileStore.GetFileNames(GetUrlCacheFilename(url)).Length > 0
    End Function

    ''' <summary>
    ''' Opens a file stream to a file with the supplied filename in the file store.
    ''' </summary>
    ''' <param name="filename">The filename to open.</param>
    ''' <param name="mode">File modes to use on opening the stream.</param>
    ''' <returns>FileStream instance pointing to the specified filename in the file store opened with specified mode.</returns>
    ''' <remarks></remarks>
    Public Function OpenFileStream(ByVal filename As String, ByVal mode As FileMode) As FileStream
        Return New IsolatedStorageFileStream(filename, mode, _fileStore)
    End Function

    ''' <summary>
    ''' Finds a file with the specified filename.
    ''' </summary>
    ''' <param name="filename">Filename pattern to match. Wildcards ? * are allowed.</param>
    ''' <returns>Array of filenames that matched the specified pattern.</returns>
    ''' <remarks></remarks>
    Public Function FindFiles(ByVal filename As String) As String()
        Return _fileStore.GetFileNames(filename)
    End Function

    ''' <summary>
    ''' Opens a files stream to a cached copy of the url.
    ''' </summary>
    ''' <param name="url">The requested url.</param>
    ''' <param name="mode">File mode to use on opening the stream</param>
    ''' <returns>FileStream instance pointing to the cached copy of the specified url in the file store opened with specified mode.</returns>
    ''' <remarks></remarks>
    Public Function OpenUrlCacheFileStream(ByVal url As String, ByVal mode As FileMode) As FileStream
        Return OpenFileStream(GetUrlCacheFilename(url), mode)
    End Function

    ''' <summary>
    ''' Gets a cache filename of the specified URL.
    ''' </summary>
    ''' <param name="url">The URL to construct cache filename out of.</param>
    ''' <returns>Proper cache filename to use for the specified URL.</returns>
    ''' <remarks></remarks>
    Public Function GetUrlCacheFilename(ByVal url As String) As String

        'computes a hashcode from the url
        Dim hash = url.ToLower().GetHashCode()
        Dim hashChar = (New Uri(url)).Host.Chars(0)

        'construct the cache filename
        'the format is : cache-a12345.jpg.qt!
        ' "cache" is appended so all cache files can be located with ease
        ' "a12345.jpg" is the hashed filename of the url
        ' "qt!" added to avoid any possibility of filename conflicts
        Return CACHEPREFIX + hashChar + hash.ToString() + Path.GetExtension(url) + CACHESUFFIX

    End Function

    ''' <summary>
    ''' Truncates the cache size down to the specified value.
    ''' </summary>
    ''' <param name="totalFileStoreSize">Maximum size of the
    ''' file store with all the caches. The leftover portion or the cache will be truncated.</param>
    Public Sub TruncateCache(ByVal totalFileStoreSize As Long)

        'gets a list of cached files inside the file store
        'return if no cache exists for any truncation
        Dim files = FindFiles(CACHEPREFIX + "*" + CACHESUFFIX)

        If files.Length = 0 Then Return

        Dim idx = files.Length - 1

        'keep deleting the cache until we get at the needed size
        'or the cache are depleted
        While _fileStore.CurrentSize > totalFileStoreSize AndAlso idx >= 0
            _fileStore.DeleteFile(files(idx))
            idx -= 1
        End While

    End Sub

End Module
